import { upFixed, subtract } from '@/utils'
import { differenceInDays, differenceInCalendarMonths, isSameWeek } from 'date-fns'

// 计算y轴刻度值
export function yAxisNumber(list) {
  const res = []
  list = list.filter(i => i!=null)
  const min = Math.min.apply(null, list)
  const max = Math.max.apply(null, list)
  const n = Number(upFixed((max - min)/4, 2))
  // const n = Math.ceil((max - min)/4) // todo y轴颗粒度
  if(!n) {
    return [-1, 1, 1]
  }
  res[2] = n
  res[0] = Number((min - n/2).toFixed(2))
  // res[0] = Number((min - n/2).toFixed(0)) // todo y轴颗粒度
  res[1] = res[0] + n*5
  return res
}

// echarts 归0处理
export function xReturnZero(data1, data2, op, op1, baseline_i, end_i, isIndexList) {
  const all_list_obj1 = [] // 处理y轴间距
  Object.keys(data1).forEach((key, i) => {
    // if(Object.keys(op.legend[0].selected).length==0 || op.legend[0].selected[key] || op.legend[0].selected[key]==undefined) { // 之前优化算法，图例未选中不参与计算
      const list = data1[key]
      const list1 = data2[key]
      if(list.length-1 >= baseline_i) {
        let baseline_val = data1[key][baseline_i] // 收益基准--当前时间段区域收益起始值
        if(baseline_val==null) { // 如果后面连续30个值有不为null，则为基准值  解决日周月混合曲线归0问题
          for (let index = 1; index < 32; index++) {
            const val = data1[key][baseline_i+index]
            if(val) {
              baseline_val = val
              break
            }
          }
        }
        let baseline_val1 = 0 // 风险基准--当前时间段区域收益最大值
        let n = 0
        const data = list.map((item, i) => {
          if(item != null && baseline_val != null) {
            // return (Number(divide(item, baseline_val))+1).toFixed(5)
            // n = (Number(subtract(item, baseline_val))+1).toFixed(5)
            n = (Number(subtract(item, baseline_val))).toFixed(2) // pnl区间收益版
          }else {
            if(item != null) {  // 基准值为空时，且此时间初始值为null，该策略曲线不参与计算
              n = item
            }else {
              n = null
            }
          }
          if(baseline_i<=i && i<=end_i && (Object.keys(op.legend[0].selected).length==0 || op.legend[0].selected[key] || op.legend[0].selected[key]==undefined)) {
            all_list_obj1.push(n)
          }
          if(baseline_i<=i && i<=end_i && n!=null) {  // 得风险区间基准值（如果当前值大于记录值且i处于区间内，则替换‘风险基准’值）
            if(n == null) {
              list1[i] = null
            }else if(Number(n)<Number(baseline_val1)) {
              if(isIndexList.indexOf(key)==-1) {
                list1[i] = (n-baseline_val1).toFixed(2) // pnl区间收益版
              }else {
                list1[i] = ((n-baseline_val1)/(Number(baseline_val1)+100)*100).toFixed(2)
              }
            }else {
              baseline_val1 = n
              list1[i] = 0
            }
          }
          return n
        })
        op.series[i].data = data
        op1.series[i].data = list1
      }
    // }
  })
  return {op, op1, all_list_obj1}
}

/**
 * 随机数函数
 * @param {Number} n 
 * @returns 
 */
export function randomStr(n) {
  const data = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

  let result = ""
  for (let i = 0; i < n; i++) {
    const r = Math.floor(Math.random() * 62) // 取得0-62间的随机数，目的是以此当下标取数组data里的值！
    result += data[r] // 输出n次随机数的同时，让rrr加n次，就是n位的随机字符串了。
  }
  return result
}

/**
 * 随机数函数
 * @param {Number} n 
 * @returns 
 */
 export function randomNum(n) {
  const data = ["1","2","3","4","5","6","7","8","9"]

  let result = ""
  for (let i = 0; i < n; i++) {
    const r = Math.floor(Math.random() * 9) // 取得0-62间的随机数，目的是以此当下标取数组data里的值！
    result += data[r] // 输出n次随机数的同时，让rrr加n次，就是n位的随机字符串了。
  }
  return Number(result)
}

/**
 * 根据日期判断数据是日，周，月频数据
 * @param {Array} dates 日期数组
 * @returns 1.日，2.周，3.月
 */
export function chartDateFreq(dates) {
  let _dates = JSON.parse(JSON.stringify(dates))
  if(_dates.length>100) { // 只需平均截取前100位样品数据
    const dates_line = Math.floor(_dates.length/4)
    _dates = [
      ..._dates.slice(0, 26),
      ..._dates.slice(dates_line+1, dates_line*2+1),
      ..._dates.slice(dates_line*2+1, dates_line*3+1),
      ..._dates.slice(dates_line*3+1, dates_line*4+1)
    ]
  }
  const nums = [] // 每条数据的时间间隔
  _dates.map((item, i) => {
    if(i<_dates.length-1) {
      nums.push(differenceInDays(_dates[i+1], item))
    }
  })
  const l_day = nums.filter(e => e<3).length
  const l_week = nums.filter(e => e>3&&e<8).length
  const l_month = nums.filter(e => e>7).length
  const max = Math.max(l_day, l_week, l_month)
  if(max==l_day) return 1
  if(max==l_week) return 2
  if(max==l_month) return 3
}

/**
 * 根据净值条数判断数据是日，周，月频数据 （净值中间填充了null）
 * @param {Array} list 净值/pnl数组
 * @param {Array} dates x轴时间数组
 * @returns 1.日，7.周，30.月
 */
 export function chartDateFreqOnValue(list, dates) {
  let _list = JSON.parse(JSON.stringify(list))
  // let _list_realL = _list.length
  // let realL = dates.length - _list_realL
  if(_list.length>100) { // 只需平均截取100位样品数据
    const val_line = Math.floor(_list.length/4)
    _list = [
      ..._list.slice(0, 26),
      ..._list.slice(val_line+1, val_line*2+1),
      ..._list.slice(val_line*2+1, val_line*3+1),
      ..._list.slice(val_line*3+1, val_line*4+1)
    ]
  }
  let nums_notNull = 0 // null的个数
  _list.forEach(n => {
    if(n!=null) nums_notNull++
  })
  const res = nums_notNull/_list.length
  if(res>0.3) return 1
  if(res>0.07&&res<=0.3) return 7
  if(res<=0.07) return 30
}


// 历史收益走势图--计算周频
export function getWeekData(dates, objs, objs1) {
  const res_dates = []
  const res_objs = {}
  const res_objs1 = {}
  Object.keys(objs).map(key => {
    res_objs[key] = []
    res_objs1[key] = []
  })
  const _dates = JSON.parse(JSON.stringify(dates))
  let base_num, base_num1
  _dates.map((date, i) => {
    if(i<_dates.length-1&&i!=0) {
      if(!isSameWeek(date, _dates[i+1])) {
        res_dates.push(date)
        let one_res_key = ''
        Object.keys(res_objs).map((res_key, res_key_i) => {
          if(res_key_i==0) one_res_key = res_key
          // 收益数据
          if(!base_num) base_num = res_objs[res_key][0]!=undefined ? res_objs[res_key][0] : objs[res_key][i]
          if(objs[res_key][i]!=null) {
            res_objs[res_key].push((objs[res_key][i]-base_num).toFixed(2)) // '-base_num' 归0
          }else {
            let num = 1
            while (isSameWeek(date, _dates[i-num])&&res_objs[res_key][res_objs[one_res_key].length]==undefined) {
              if(objs[res_key][i-num]!=null) {
                res_objs[res_key].push((objs[res_key][i-num]-base_num).toFixed(2))
              }
              num++
            }
            if(res_objs[res_key][res_objs[one_res_key].length]==undefined) res_objs[res_key].push(null)
          }
          // 回撤数据
          if(!base_num1) base_num1 = res_objs1[res_key][0]!=undefined ? res_objs1[res_key][0] : objs1[res_key][i]
          if(objs1[res_key][i]!=null) {
            const val = objs1[res_key][i]-base_num1 > 0 ? 0 : objs1[res_key][i]-base_num1
            res_objs1[res_key].push((val).toFixed(2)) // '-base_num1' 归0
          }else {
            let num = 1
            while (isSameWeek(date, _dates[i-num])&&res_objs1[res_key][res_objs1[one_res_key].length]==undefined) {
              if(objs1[res_key][i-num]!=null) {
                res_objs1[res_key].push((objs1[res_key][i-num]-base_num1).toFixed(2))
              }
              num++
            }
            if(res_objs1[res_key][res_objs1[one_res_key].length]==undefined) res_objs1[res_key].push(null)
          }
        })
      }
    }else { // 处理最后一天
      res_dates.push(date)
      Object.keys(res_objs).map(res_key => {
        if(!base_num) base_num = res_objs[res_key][0]!=undefined ? res_objs[res_key][0] : objs[res_key][i]
        if(objs[res_key][i]!=null) {
          res_objs[res_key].push((objs[res_key][i]-base_num).toFixed(2)) // '-base_num' 归0
        }else {
          res_objs[res_key].push(null)
        }
        // 回撤数据
        if(!base_num1) base_num1 = res_objs1[res_key][0]!=undefined ? res_objs1[res_key][0] : objs1[res_key][i]
        if(objs1[res_key][i]!=null) {
          const val = objs1[res_key][i]-base_num1 > 0 ? 0 : objs1[res_key][i]-base_num1
          res_objs1[res_key].push((val).toFixed(2)) // '-base_num' 归0
        }else {
          res_objs1[res_key].push(null)
        }
      })
    }
  })
  return [res_dates, res_objs, res_objs1]
}


// 历史收益走势图--计算月频
export function getMonthData(dates, objs, objs1) {
  const res_dates = []
  const res_objs = {}
  const res_objs1 = {}
  Object.keys(objs).map(key => {
    res_objs[key] = []
    res_objs1[key] = []
  })
  const _dates = JSON.parse(JSON.stringify(dates))
  let base_num, base_num1
  _dates.map((date, i) => {
    if(i<_dates.length-1&&i!=0) {
      const dateComs = date.split('-')
      const next_dateComs = _dates[i+1].split('-')
      if(!(dateComs[0]==next_dateComs[0] && Number(dateComs[1])==Number(next_dateComs[1]))) {
        res_dates.push(date)
        let one_res_key = ''
        Object.keys(res_objs).map((res_key, res_key_i) => {
          if(res_key_i==0) one_res_key = res_key
          // 收益数据
          if(!base_num) base_num = res_objs[res_key][0]!=undefined ? res_objs[res_key][0] : objs[res_key][i]
          if(objs[res_key][i]!=null) {
            res_objs[res_key].push((objs[res_key][i]-base_num).toFixed(2)) // '-base_num' 归0
          }else {
            let num = 1
            while (dateComs==_dates[i-num].split('-')[0]&&res_objs[res_key][res_objs[one_res_key].length]==undefined) {
              if(objs[res_key][i-num]!=null) {
                res_objs[res_key].push((objs[res_key][i-num]-base_num).toFixed(2))
              }
              num++
            }
            if(res_objs[res_key][res_objs[one_res_key].length]==undefined) res_objs[res_key].push(null)
          }
          // 回撤数据
          if(!base_num1) base_num1 = res_objs1[res_key][0]!=undefined ? res_objs1[res_key][0] : objs1[res_key][i]
          if(objs1[res_key][i]!=null) {
            const val = objs1[res_key][i]-base_num1 > 0 ? 0 : objs1[res_key][i]-base_num1
            res_objs1[res_key].push((val).toFixed(2)) // '-base_num' 归0
          }else {
            let num = 1
            while (dateComs==_dates[i-num].split('-')[0]&&res_objs1[res_key][res_objs1[one_res_key].length]==undefined) {
              if(objs1[res_key][i-num]!=null) {
                res_objs1[res_key].push((objs1[res_key][i-num]-base_num1).toFixed(2))
              }
              num++
            }
            if(res_objs1[res_key][res_objs1[one_res_key].length]==undefined) res_objs1[res_key].push(null)
          }
        })
      }
    }else { // 处理最后一天
      res_dates.push(date)
      Object.keys(res_objs).map(res_key => {
        // 收益数据
        if(!base_num) base_num = res_objs[res_key][0]!=undefined ? res_objs[res_key][0] : objs[res_key][i]
        if(objs[res_key][i]!=null) {
          res_objs[res_key].push((objs[res_key][i]-base_num).toFixed(2)) // '-base_num' 归0
        }else {
          res_objs[res_key].push(null)
        }
        // 回撤数据
        if(!base_num1) base_num1 = res_objs1[res_key][0]!=undefined ? res_objs1[res_key][0] : objs1[res_key][i]
        if(objs1[res_key][i]!=null) {
          const val = objs1[res_key][i]-base_num1 > 0 ? 0 : objs1[res_key][i]-base_num1
          res_objs1[res_key].push((val).toFixed(2)) // '-base_num' 归0
        }else {
          res_objs1[res_key].push(null)
        }
      })
    }
  })
  return [res_dates, res_objs, res_objs1]
}

/**
 * 
 * @param {Object} objs 折线数据
 * @returns 每条数据的风险指标
 */
export function riskIndexCalc(objs) {
  const res = []
  const objs1 = JSON.parse(JSON.stringify(objs[0]))
  const objs2 = JSON.parse(JSON.stringify(objs[1]))
  
  Object.keys(objs1).forEach((key, index) => {
    //  数据前后去null
    let dates = JSON.parse(JSON.stringify(objs[2]))
    let obj2 = objs2[key]
    const res_afterClearNull = listAfterClearNull(objs1[key])
    dates = dates.slice(0, dates.length-res_afterClearNull[1])
    obj2 = obj2.slice(0, obj2.length-res_afterClearNull[1])
    const res_beforeClearNull = listBeforeClearNull(res_afterClearNull[0])
    dates = dates.slice(res_beforeClearNull[1])
    obj2 = obj2.slice(res_beforeClearNull[1])
    const obj1 = res_beforeClearNull[0]
    
    if(obj1.length) {
      if(!res[index]) res[index] = {name: key}
      // 收益率
      res[index].incomeRate = obj1[obj1.length-1]
      // 年化收益率
      let dm = differenceInCalendarMonths(objs[2][objs[2].length-1], objs[2][0])
      dm = dm || 1
      res[index].annualizedIncomeRate = (obj1[obj1.length-1] / (dm/12)).toFixed(2)
      // 最大回撤
      const maximumDrawdownRate = Math.min.apply(null, obj2)
      res[index].maximumDrawdownRate = maximumDrawdownRate*-1+ '%'
      // 最大回撤回补期(1)
      const startDrawdownDate_i = obj2.findIndex(el => el==maximumDrawdownRate)
      let drawdown_max_afterIncomeRate // 最大回撤前的最大收益
      const drawdown_max_afterIncomeRate_date = dates[startDrawdownDate_i] // 最大回撤前最大收益日期
      let drawdown_flat_afterIncomeRate_date // 最大回撤后平仓日期
      // 最大不创新高天数(1)
      const notByNewHightDayList = []
      let tag = 0 // 标记是否处于记录中
      let tag_notByNewHightDay0 = '' 
      let tag_notByNewHightDay1 = ''
      // 胜率
      let winningNum = 0
      let winningLength = obj1.length // 记录非null的长度
      let tag_winning_val // 用于标记胜率算法中连续存在null值时上一次存在的收益率
      // 年化波动率
      let sum = 0
      let avg = 0
      let valid_val1 = 0
      for (let i = 0, j = obj1.length; i < j; i++) {
        if(obj1[i]!=null) {
          sum += Number((obj1[i]-valid_val1)/100)
          
          // 辅助 胜率 计算
          if(i==0) {
            winningNum++   // 和后端算法保持一致
          }else if(!tag_winning_val) {
            if(Number(obj1[i])>Number(obj1[i-1])) winningNum++
          }else {
            tag_winning_val = undefined
            if(Number(obj1[i])>tag_winning_val) winningNum++
          }
          valid_val1 = obj1[i]
        }else {
          if(!tag_winning_val) {
            tag_winning_val = Number(obj1[i-1])
          }
          winningLength--
        }

        // 辅助 最大回撤回补期 计算
        if(i<startDrawdownDate_i) {
          if((!drawdown_max_afterIncomeRate) || Number(obj1[i])>Number(drawdown_max_afterIncomeRate)) {
            drawdown_max_afterIncomeRate = obj1[i]
            // drawdown_max_afterIncomeRate_date = dates[i]  // 从回撤前最大收益处得 最大回撤回补期 开始时间
          }
        }else {
          if((!drawdown_flat_afterIncomeRate_date)&&Number(obj1[i])>=Number(drawdown_max_afterIncomeRate)) drawdown_flat_afterIncomeRate_date = dates[i]
        }
        // 辅助 最大不创新高天数 计算
        let tag_notByNewHight
        obj2[i] == null ? tag_notByNewHight = (obj2[i-1]+obj2[i+1])/2 : tag_notByNewHight = obj2[i]  // todo 存在前后也为null的情况
        if(Number(tag_notByNewHight)!=0) {  // 回撤不为0则走低起始 tag_notByNewHightDay0记录此次走低的开始日期
          if(!tag && dates[i-1]) {
            tag_notByNewHightDay0 = dates[i-1]
            // if(key=='标普500') console.log(`%c开始日期 ${tag_notByNewHightDay0}`, 'color: green');
          }
          tag = 1
          if(i==j-1&&tag_notByNewHightDay0!='') { // 兜底 最后还处于走低的趋势
            if(dates[i]&&tag_notByNewHightDay0) notByNewHightDayList.push(differenceInDays(dates[i], tag_notByNewHightDay0))
            // if(key=='标普500') console.log(`%c结束日期 ${dates[i]} ${differenceInDays(dates[i], tag_notByNewHightDay0)}`, 'color: red');
          }
        }else {  // 回撤为0则创新高 tag_notByNewHightDay1记录此次的结束日期
          if(tag) {
            tag_notByNewHightDay1 = dates[i]
            if(tag_notByNewHightDay0&&tag_notByNewHightDay1) notByNewHightDayList.push(differenceInDays(tag_notByNewHightDay1, tag_notByNewHightDay0))
            // if(key=='标普500') console.log(`%c结束日期 ${tag_notByNewHightDay1} ${differenceInDays(tag_notByNewHightDay1, tag_notByNewHightDay0)}`, 'color: red');
          }
          tag = 0
        }
      }
      // avg = sum / l 
      avg = sum / winningLength // 处理计算波动时净值有缺失的情况
      let num = 0
      let valid_val2 = 0
      obj1.forEach((n, i) => {
        if(n!=null) {
          num = num + ((n-valid_val2)/100-avg)*((n-valid_val2)/100-avg)
          valid_val2 = n
        }
      })
      // 判断频率类型
      const datesFreq = dateFreqHandle(obj1, dates)
      const freqList = [1, 7, 30]
      const freq = chartDateFreq(datesFreq)
      const annualFluctuationsRate = Math.sqrt(num*(365/freqList[freq-1])/(winningLength-1))*100
      res[index].annualFluctuationsRate = annualFluctuationsRate.toFixed(2) + '%'
      // 最大回撤回补期(2)
      if(drawdown_max_afterIncomeRate_date&&drawdown_flat_afterIncomeRate_date) {
        res[index].maxBackIncomDay = differenceInDays(drawdown_flat_afterIncomeRate_date, drawdown_max_afterIncomeRate_date)
      }else {
        res[index].maxBackIncomDay = null
        // res[index].maxBackIncomDay = 0
      }
      // 最大不创新高天数(2)
      // res[index].maxNotByNewHightDay = notByNewHightDayList.length ? Math.max.apply(null, notByNewHightDayList) : null
      res[index].maxNotByNewHightDay = notByNewHightDayList.length ? Math.max.apply(null, notByNewHightDayList) : 0
      // 夏普比率
      if(Number(annualFluctuationsRate)==0) {
        res[index].sharpeRate = '--'
      }else {
        res[index].sharpeRate = Math.abs((res[index].annualizedIncomeRate-2) / annualFluctuationsRate).toFixed(2) // 年化收益-2 2为固收
      }
      // 卡玛比率
      if(Number(maximumDrawdownRate)==0) {
        res[index].calmarRate = '--'
      }else {
        res[index].calmarRate = Math.abs(res[index].annualizedIncomeRate / maximumDrawdownRate*-1).toFixed(2)
      }
      // 胜率
      res[index].investWinningRate = (winningNum/winningLength*100).toFixed(2) + '%'
    }else {
      res[index] = {
        name: key,
        annualFluctuationsRate: '--',
        annualizedIncomeRate: null,
        calmarRate: "--",
        sharpeRate: '--',
        incomeRate: null,
        maxBackIncomDay: '--',
        maximumDrawdownRate: '--',
        maxNotByNewHightDay: '--',
        investWinningRate: '--',
      }
    }
  })
  return res
}

// 数据为null清除日期
function dateFreqHandle(list, dates) {
    const res = []
    for (let i = 0, j = list.length; i < j; i++) {
      if(list[i]!=null) res.push(dates[i])
    }
    return res
}
// 清除数组末位连续的null & 清除了多少
export function listAfterClearNull(list) {
  let num = 0
  let res = JSON.parse(JSON.stringify(list))
  while (res.length&&res[res.length-1]==null) {
    num++
    if(res.length==1&&res[0]==null) {
      res = []
    }else {
      res.pop()
    }
  }
  return [res, num]
}
// 清除数组前位连续的null
function listBeforeClearNull(list) {
  let num = 0
  let res = JSON.parse(JSON.stringify(list))
  while (res.length&&res[0]==null) {
    num++
    if(res.length==1&&res[0]==null) {
      res = []
    }else {
      res.shift()
    }
  }
  return [res, num]
}
// 清除数组所有的null
// function listClearNull(list) {
//   const res = []
//   for (let i = 0, j = list.length; i < j; i++) {
//     if(list[i]!=null) res.push(list[i])
//   }
//   return res
// }


